import { Socket } from 'socket.io';
import subscribe from '../src/socket/subscribe';
import unsubscribe from '../src/socket/unsubscribe';
import disconnect from '../src/socket/disconnect';
import message from '../src/socket/message';
import notice from '../src/socket/notice';
import room from './middlewares/room';
import { middlewares } from './middlewares';
import administrator from './administrator';
// import connection from './connection';
import WebRTCServer from '../src/webrtc';
import { Member, Members, MemberProxy } from "../src/lib/Member";
import {
  ChatModeEnums, InviteModeEnums, JoinModeEnums, MemberStateEnums, RoomTypeEnums, CallingEnums
} from "../src/utils/enums";
// import { Room, Rooms } from "../lib/Rooms";
// import { ClaUser } from "../model/model";
// import {SocketId} from "socket.io-adapter";

const classType = RoomTypeEnums.RESIDENT;
const inviteMode = InviteModeEnums.NO_VERIFY;
const joinMode = JoinModeEnums.NO_VERIFY;
const chatMode = ChatModeEnums.GROUP;

interface queryTypes {
  [key: string]: string
}

export default function runWebSocketServer (app) {
  const { io } = app.locals;
  const intercom = io.of('/intercom');

  // webSocket
  intercom.on('connection', async function (socket: Socket) {
    // const url = socket.request.headers.referer;
    const query = socket.handshake.query as queryTypes;
    const { classId, classname, userId, username } = query;
    const __owner = Member.proxy({
      userId, username, socketId: socket.id
    }, intercom);

    app.locals.socket = socket;
    app.locals.intercom = intercom;

    // console.log('__owner: => ', __owner)
    console.log('connection: => ', { userId, username })

    function connection () {
      intercom[userId] = socket;

      /*if (classId) {
        // 加入 常驻房间
        socket.join(classId);
        __owner.setClassroom(classId)

        // 储存常驻房间用户列表
        if (!Rooms.has(classId)) {
          Rooms.set(classId, new Room({
            classId, classname, classType, inviteMode, joinMode, chatMode
          }))
        }

        {
          (Rooms.get(classId) as Room).setMember(__owner);
        }
      }*/

      /*setInterval(() => {
        const __owner = Members.get(userId);
        if (__owner) {
          __owner.state = __owner.state === MemberStateEnums.FREE ? MemberStateEnums.BUSY : MemberStateEnums.FREE
        }
      }, 200)*/


      // 中间件
      middlewares(socket);

      // 管理员
      administrator(app, io);
      console.log('------------------- administrator -----------------------')

      // 管理房间
      room(app, io);

      // 客户端的send方法发送的消息
      message(app);

      // WebRTC 服务
      WebRTCServer(app);

      // 通知指定 userId 的用户
      notice(app);

      // 订阅
      subscribe(app);

      // 退订
      unsubscribe(app);

      // 断开连接
      disconnect(app);

      __owner.state = MemberStateEnums.FREE
      // __owner.state = MemberStateEnums.BUSY
      Members.set(userId, __owner);
    }

    /*try {
      const userData = {
        userId: userId,
        username: username,
        clientType: 3,
        state: '3',
        createTime: Date.now().toString(),
        lastActiveTime: Date.now().toString(),
      }

      const hasUser = await ClaUser.findOne({ where: { userId }})

      if (!hasUser) {
        const dbUser = new ClaUser();
        Object.assign(dbUser, userData)
        /!*dbUser.id = 'xxxxxxxxx' + ~new Date();
        dbUser.name = '张三';
        dbUser.clientType = 2;
        dbUser.createTime = Date.now().toString();
        dbUser.lastActiveTime = Date.now().toString();*!/

        console.log(dbUser)
        await dbUser.save({ data: dbUser })
      }
    } catch (error) {
      console.log(error)
    }*/

    /**
     * 登陆时判断用户是否重复登陆。
     * 如果重复登陆，则让用户选择，是放弃，还是强制登陆。
     */
    if (Members.has(userId)) {
      app.locals.intercom[userId].disconnect()
      connection()

      console.log(CallingEnums)
      /**
       * 等待 3 分钟
       * 用户重复登陆，是放弃登陆，还是将对方挤下去。
       * 让用户自己决定
       * 如果用户不决定，那么默认会登陆失败，将用户 socket 断掉。
       * 客户端可以设置 3 分钟之内的其他时间长度，断掉连接。
       *
       * let exec;
       * socket.on('repeat', (data, callback) => {
       *   exec = function () {
       *     callback()
       *     callback = null
       *   }
       *   setTimeout(() => {
       *     if (callback) callback(false)
       *   }, 1000 * 60)
       * })
       */
      /*
      const repeatOption = {
        status: 'error',
        message: 'Repeat login'
      }
      socket
        .timeout(1000 * 10)
        .emit('repeat', repeatOption, (error, data) => {

          console.log(error, data)
        if (error) {
          socket.emit('socket-error', {
            status: 'error',
            message: 'Repeat login'
          })
          socket.disconnect()
        } else {
          if (data) {
            const { status } = data;
            if (status === CallingEnums.AGREE) {
              // 通知已登陆角色，有人将他挤掉线。
              // 将已登陆角色下线，然后使用当前新的socket重新建立连接
              // 等待 300 毫秒，保证信息发给了用户。
              // 用户收到信息，是要现实被挤下线的弹出框的，
              app
                .locals
                .intercom[userId]
                .timeout(300)
                .emit('socket-repeat', {
                  status: 'error',
                  message: 'Repeat login'
                }, () => {
                  app.locals.intercom[userId].disconnect()
                  connection()
                })
            } else {
              // 放弃登录，销毁连接。
              socket
                .timeout(300)
                .emit('socket-repeat', {
                  status: 'error',
                  message: 'Repeat login'
                }, () => {
                  socket.disconnect()
                })
            }
          }
        }
      })*/
    } else {
      connection()
    }

    console.log('connection')
    // Join room
    // Exit room
  });

  io.on('leave', function () {
    console.log('-----------');
    io.emit('disconnect');
  });
}
